/*
 * DotGadu 2007/2008
 * WWW: http://dotgadu.sf.net/
 * E-MAIL: dominikcebula@gmail.com
 *
 * Projekt biblioteki, ktorej celem jest obsluga protokolu GaduGadu z poziomu .NET. Opis protokolu zostal
 * zaczerpniety z libgadu, mozna go znalezc tutaj: http://ekg.chmurka.net/docs/protocol.html
*/

using System;
using System.IO;
using System.Net.Sockets;
using System.Net;

namespace GG_Network.Gadu {
    /// <summary>
    /// Wyjatek zwracany podczas pobierania adresu ip i portu z appmsg.gadu-gadu.pl
    /// </summary>
    public class GaduServerException : Exception    // nasz wlasny wyjatek
    {
        /// <summary>
        /// Wyjatek zwracany podczas pobierania adresu ip i portu z appmsg.gadu-gadu.pl
        /// </summary>
        public GaduServerException(String message) : base(message) { }  // dziedziczenie konstruktora
    }

    /// <summary>
    /// Klasa, ktora pobiera ip oraz port z appmsg.gadu-gadu.pl. Istnieje rowniez mozliwosc podania tych danych
    /// tak aby nie trzeba bylo ich pobierac z servera.
    /// </summary>
    public class GaduServer {
        private TcpClient tcpClient;    // gniazdo
        private String host;    // adres ip servera gg, ktory zostanie pobrany z appmsg.gadu-gadu.pl
        private int port;       // port na ktory mamy sie polaczyc
        private int uin;        // nr. gg dla, ktorego chcemy pobrac adres ip servera
        private StreamReader socketIn;  // za pomoca StreamReader bedziemy czytac informacje z gniazda, glownie ReadLine() :)
        private NetworkStream socketOut;    // do wysylania danych uzyjemy NetworkStream i funkcji WriteByte(), aby wyslac znak w formacie ASCII, a nie UTF-8

        private int timeOut;        // czas na polaczenie do servera

        /// <summary>
        /// Adres ip servera gadu-gadu
        /// </summary>
        /// <value>Adres ip servera gadu-gadu</value>
        public String Host  // zwracanie Host-a
        {
            get {
                return host;
            }
        }

        /// <summary>
        /// Port servera gadu-gadu
        /// </summary>
        /// <value>Port servera gadu-gadu</value>
        public int Port // zwracanie Portu
        {
            get {
                return port;
            }
        }

        /// <summary>
        /// Czas po ktorym uznajemy ze dany server gadu-gadu nie odpowiada, jest martwy.
        /// </summary>
        public int TimeOut  // zwracanie/ustawianie timeOut
        {
            set {
                TimeOut = value;
                tcpClient.ReceiveTimeout = timeOut;
                tcpClient.SendTimeout = timeOut;
            }
            get {
                return timeOut;
            }
        }

        /// <summary>
        /// UWAGA wystepuje PROBLEM z pobieraniem adresow z hub gg, ZALECA sie uzywanie konstruktora GaduServer(String host, int port)
        /// 
        /// Konstruktor do ktorego podajemy numer gg, na podstawie nr. gg appmsg.gadu-gadu.pl wybiera nam odpowiedni
        /// server
        /// </summary>
        /// <param name="uin">Numer gg</param>
        public GaduServer(int uin)  // konstruktor w ktorym podajemy uin dla ktorego adres ip hosta i portu zostanie pobrany z servera
        {
            tcpClient = new TcpClient( );    // tworzymy gniazdo
            this.uin = uin;   // ustawiamy uin

            tcpClient.ReceiveTimeout = 5000;    // ustawiamy nasz domyslny timeOut
            tcpClient.SendTimeout = 5000;
            timeOut = 5000;
            getServer( );    // pobieramy adres ip servera gadu-gadu dla naszego uin
        }

        /// <summary>
        /// Konstruktor, ktory wpisze dane o adres ip server i port, nie sa one wiec pobierane z appmsg.gadu-gadu.pl
        /// </summary>
        /// <param name="host">Adres ip servera gadu-gadu</param>
        /// <param name="port">Port servera gadu-gadu</param>
        public GaduServer(String host, int port)    // jezeli chcemy podac adres servera gadu-gadu i jego port, a nie pobierac tych danych z appmsg.gadu-gadu.pl
        {
            this.host = host;
            this.port = port;
        }

        /// <summary>
        /// Pobiera adres ip oraz port z servera gadu-gadu
        /// </summary>
        /// <exception cref="GaduServerException">GaduServerException</exception>
        private void getServer( ) {
            const int bufSize = 8192;
            System.Text.StringBuilder StrBuilder;


            try {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://appmsg.gadu-gadu.pl/appsvc/appmsg_ver8.asp?fmnumber=" + uin); //rządanie GET za pomocą klasy HttpWebRequest
                HttpWebResponse response = (HttpWebResponse)request.GetResponse( );//odbowiedź na rządanie
                Stream responseStream = response.GetResponseStream( );//odczytanie strumienia danych odpowiedzi
                int responseLength = (int)response.ContentLength;
                byte[ ] data = new byte[bufSize];
                StrBuilder = new System.Text.StringBuilder(bufSize);

                while ((responseLength = responseStream.Read(data, 0, data.Length)) != 0)//przetworzenie danych otrzymanych
                { StrBuilder.Append(System.Text.Encoding.UTF8.GetString(data, 0, responseLength)); }// na łańcuch string

                String receivedString = Convert.ToString(StrBuilder);
                String[ ] hostIP = receivedString.Split(Convert.ToChar(" "));//podzielenie łańcucha na segmenty
                host = hostIP[3].TrimEnd( ); //uzyskanie hosta
                string[ ] port_array = hostIP[2].Split(':');
                port = Convert.ToInt32(port_array[1]);//usyzkanie portu
            } catch (Exception e) {
                throw new GaduServerException(e.Message);
            }
        }
    }
}